/*
 *                    COPYRIGHT NOTICE
 *
 *           This code is copyright protected by Freedom Inc.
 *
 *              2001-2012 All Rights Are Reserved
 */
package com.freedom.oldsong.interceptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;

import com.freedom.oldsong.common.Finder;
import com.freedom.oldsong.common.Pagination;
import com.freedom.oldsong.system.BaseDao;
import com.freedom.oldsong.system.dto.PaginationResult;

/**
 * @author steven.wang
 *
 */
public class OldsongDaoInterceptor implements MethodInterceptor {

	private static final Logger logger=Logger.getLogger(OldsongDaoInterceptor.class);
	
	/**
	 * {@inheritDoc}
	 */
	public Object invoke(MethodInvocation methodInvocation) throws Exception{
		try{
			Object source = methodInvocation.getThis();
			Method method = methodInvocation.getMethod();
			String queryName = null;
			Object[] arguments = methodInvocation.getArguments();
			
			Annotation[] annotations = method.getAnnotations();
			if(annotations != null && annotations.length >0){
				for(int i = 0; i < annotations.length; i++){
					if(annotations[i] instanceof Finder){
						queryName = ((BaseDao)source).getNameMapping() + "."+ ("".equals(((Finder)annotations[i]).query())?method.getName():((Finder)annotations[i]).query());
						if(method.getReturnType().equals(List.class)){
							return ((BaseDao)source).queryForList(queryName, arguments);
						}else{
							return ((BaseDao)source).queryForObject(queryName, arguments);
						}
					}
					else if(annotations[i] instanceof Pagination){
						return pagination(source, method, arguments,
								annotations, i);
					}
				}
			}
			return method.invoke(source, arguments);
		} 
		catch (DataAccessException e) {
			logger.error(e.getMessage());
			throw e;
		}
	}

	/**
	 * @param source
	 * @param method
	 * @param arguments
	 * @param annotations
	 * @param i
	 * @return
	 */
	private Object pagination(Object source, Method method, Object[] arguments,
			Annotation[] annotations, int i) {
		String queryName;
		queryName = ((BaseDao)source).getNameMapping() + "."+ ("".equals(((Pagination)annotations[i]).query())?method.getName():((Pagination)annotations[i]).query());
		PaginationResult paginationResult=null;
		Object[] args = new Object[arguments.length-1];
		int offset=0;
		for(int j=0; j<arguments.length;j++){
			Object arg = arguments[j];
			if(arg instanceof PaginationResult){
				paginationResult=(PaginationResult)arg;
				offset=1;
				continue;
			}
			args[j-offset]=arguments[j];
		}
		return ((BaseDao)source).selectForPagination(queryName,paginationResult,args);
	}
}